home *** CD-ROM | disk | FTP | other *** search
/ 10,000 Great Games / 10,000 Great Games.iso / Product / 66 / data1.cab / Source_Files / Src / Editable.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-16  |  11.6 KB  |  568 lines

  1. #include "stdafx.h"
  2.  
  3. #include "MstructDlg.h"
  4. #include "TurretDlg.h"
  5.  
  6. cEditable *editables = 0;
  7. int selectionbox_active = FALSE, snap_to_grid = FALSE;
  8.  
  9. static cBox back_selection, game_selection;
  10. static int tmp_x, tmp_y, tmp_x2, tmp_y2, dist;
  11. static cEditable *found;
  12.  
  13. cEditable::cEditable(cEditable **list, cGameObject *_obj, int select)
  14. {
  15.     ASSERT(_obj != 0);
  16.     
  17.     obj = _obj;
  18.     sub_editables = 0;
  19.     selected = select;
  20.  
  21.     // Add to list
  22.  
  23.     add((cList **)list);
  24.  
  25.     // Set surface
  26.  
  27.     set_surface(obj->surface);
  28.  
  29.     // Create pointer to this in original object
  30.  
  31.     if (obj->editable == 0)
  32.         obj->editable = this;
  33. }
  34.  
  35. cEditable::~cEditable()
  36. {
  37.     // Make sure no pointer remains to this object
  38.  
  39.     if (left_editable == this)
  40.         left_editable = 0;
  41.     
  42.     // Delete sub editables
  43.  
  44.     sub_editables->delete_list();
  45.  
  46.     // Remove binding with original object
  47.  
  48.     if (obj->editable == this)
  49.         obj->editable = 0;
  50. }
  51.  
  52. static int find_editable(cEditable *e)
  53. {
  54.     int d = d_square(e->x - tmp_x, e->y - (tmp_y - game_surface->start + e->obj->surface->start));
  55.  
  56.     if (d < dist)
  57.         dist = d, found = e;
  58.  
  59.     return TRUE;
  60. }
  61.  
  62. cEditable *cEditable::find(int x, int y)
  63. {
  64.     found = 0, dist = 25, tmp_x = x, tmp_y = y;
  65.  
  66.     walk_editables(find_editable);    
  67.     
  68.     return found;
  69. }
  70.  
  71. static int check_remove_editable(cEditable *e)
  72. {
  73.     return !e->selected && !e->on_screen();
  74. }
  75.  
  76. void cEditable::make_editables()
  77. {
  78.     cEditable *e, *n;
  79.  
  80.     // If selection box is not active then delete editables that go off screen
  81.     // and that are not selected
  82.  
  83.     if (!selectionbox_active)
  84.         for (e = editables; e != 0; e = n)
  85.         {
  86.             n = (cEditable *)e->next;
  87.  
  88.             if (check_remove_editable(e) && e->walk_sub_editables(check_remove_editable))
  89.                 delete e;
  90.         }
  91.  
  92.     // Loop through all objects that can be edited and add the ones that are
  93.     // not in the list yet
  94.  
  95.     for (int i = 0; objtypes[i].type != 0; i++)
  96.         if (!objtypes[i].list_occured_earlier)
  97.             for (cGameObject *g = *objtypes[i].onscreen; g != 0; g = (cGameObject *)g->next)
  98.                 if (g->editable == 0 && g->surface_visible())
  99.                     g->create_editables();
  100. }
  101.  
  102. void cEditable::delete_editables()
  103. {
  104.     editables->delete_list();
  105. }
  106.  
  107. void cEditable::editables_layer_change()
  108. {
  109.     // First delete everything that is not in a visible layer
  110.  
  111.     cEditable *e, *n;
  112.  
  113.     for (e = editables; e != 0; e = n)
  114.     {
  115.         n = (cEditable *)e->next;
  116.  
  117.         if (!e->surface_visible())
  118.             delete e;
  119.     }
  120.  
  121.     // Then call standard function to create editables
  122.  
  123.     cEditable::make_editables();
  124. }
  125.  
  126. static int write_editable(cEditable *e)
  127. {
  128.     e->write();
  129.  
  130.     return TRUE;
  131. }
  132.  
  133. void cEditable::write_editables()
  134. {
  135.     // Walk through editables and write them
  136.  
  137.     walk_editables(write_editable);
  138.  
  139.     // Write selection box
  140.  
  141.     if (selectionbox_active)
  142.     {
  143.         if (view_backgroundarea)
  144.             rect(back_surface, back_selection.x1, back_selection.y1, back_selection.x2, back_selection.y2, blue);
  145.  
  146.         if (view_gamearea)
  147.             rect(game_surface, game_selection.x1, game_selection.y1, game_selection.x2, game_selection.y2, white);
  148.     }
  149. }
  150.  
  151. static int check_drag_editable(cEditable *e)
  152. {
  153.     if (!e->selected)
  154.         return TRUE;
  155.  
  156.     if (e->surface == back_surface)
  157.         return e->check_drag(tmp_x, tmp_y);
  158.     else 
  159.         return e->check_drag(tmp_x2, tmp_y2);
  160. }
  161.  
  162. static int drag_editable(cEditable *e)
  163. {
  164.     if (e->selected)
  165.     {
  166.         if (e->surface == back_surface)
  167.             e->drag(tmp_x, tmp_y);
  168.         else
  169.             e->drag(tmp_x2, tmp_y2);
  170.     }
  171.  
  172.     return TRUE;
  173. }
  174.  
  175. void cEditable::drag_editables(int dx_back, int dy_back, int dx_game, int dy_game)
  176. {
  177.     // Check if there is change
  178.  
  179.     if (dx_back == 0 && dy_back == 0 && dx_game == 0 && dy_game == 0)
  180.         return;
  181.  
  182.     // Setup variables
  183.  
  184.     tmp_x = dx_back, tmp_y = dy_back;
  185.     tmp_x2 = dx_game, tmp_y2 = dy_game;
  186.  
  187.     // Check if drag is possible
  188.  
  189.     if (!walk_editables(check_drag_editable))
  190.         return;
  191.  
  192.     // Drag editables
  193.  
  194.     walk_editables(drag_editable);
  195. }
  196.  
  197. void cEditable::snap_editables_to_grid()
  198. {
  199.     int dy = (left_editable->y - left_editable->obj->surface->start + game_surface->start) % LEVEL_VTICK;
  200.         
  201.     if (dy < LEVEL_VTICK / 2)
  202.         dy = - dy;
  203.     else
  204.         dy = LEVEL_VTICK - dy;
  205.  
  206.     drag_editables(0, dy, 0, dy);
  207. }
  208.  
  209. static int unselect_editable(cEditable *e)
  210. {
  211.     e->selected = FALSE;
  212.  
  213.     return TRUE;
  214. }
  215.  
  216. void cEditable::unselect_editables()
  217. {
  218.     walk_editables(unselect_editable);
  219. }
  220.  
  221. static int check_anything_selected(cEditable *e)
  222. {
  223.     return !e->selected;
  224. }
  225.  
  226. int cEditable::anything_selected()
  227. {
  228.     return !walk_editables(check_anything_selected);
  229. }
  230.  
  231. static int delete_selected_editable(cEditable *e)
  232. {
  233.     if (e->selected)
  234.         e->remove();
  235.  
  236.     return TRUE;
  237. }
  238.  
  239. void cEditable::delete_selected_editables()
  240. {
  241.     // Delete editables and objects
  242.  
  243.     walk_editables(delete_selected_editable);
  244.  
  245.     // Delete things that can be generated during the previous step
  246.  
  247.     parts->delete_list();
  248.     effects->delete_list();
  249. }
  250.  
  251. void cEditable::set_rectangle(int x, int y)
  252. {
  253.     back_selection.x1 = x;
  254.     back_selection.y1 = y - game_surface->start + back_surface->start;
  255.     
  256.     game_selection.x1 = x;
  257.     game_selection.y1 = y;
  258.     
  259.     set_edge_rectangle(x, y);
  260.     
  261.     selectionbox_active = TRUE;
  262. }
  263.  
  264. void cEditable::set_edge_rectangle(int x, int y)
  265. {
  266.     back_selection.x2 = x;
  267.     back_selection.y2 = y - game_surface->start + back_surface->start;
  268.  
  269.     game_selection.x2 = x;
  270.     game_selection.y2 = y;
  271. }
  272.  
  273. static int select_editable(cEditable *e)
  274. {
  275.     if (e->surface == game_surface)
  276.     {
  277.         if (in(e->x, game_selection.x1, game_selection.x2) && in(e->y, game_selection.y1, game_selection.y2))
  278.             e->selected = !e->selected;
  279.     }
  280.     else if (e->surface == back_surface)
  281.     {
  282.         if (in(e->x, back_selection.x1, back_selection.x2) && in(e->y, back_selection.y1, back_selection.y2))
  283.             e->selected = !e->selected;
  284.     }
  285.  
  286.     return TRUE;
  287. }
  288.  
  289. void cEditable::rectangle_to_selection()
  290. {    
  291.     // Turn of selection mode
  292.  
  293.     selectionbox_active = FALSE;
  294.  
  295.     // Sort coordinates
  296.  
  297.     sort2(back_selection.x1, back_selection.x2);
  298.     sort2(back_selection.y1, back_selection.y2);
  299.  
  300.     sort2(game_selection.x1, game_selection.x2);
  301.     sort2(game_selection.y1, game_selection.y2);
  302.  
  303.     // Toggle selection in the selection box
  304.  
  305.     walk_editables(select_editable);    
  306. }
  307.  
  308. int cEditable::walk_editables(int (*callback)(cEditable *e))
  309. {
  310.     cEditable *e, *n;
  311.  
  312.     for (e = editables; e != 0; e = n)
  313.     {
  314.         n = (cEditable *)e->next;
  315.  
  316.         if (!e->walk_sub_editables(callback))
  317.             return FALSE;
  318.  
  319.         if (!callback(e))
  320.             return FALSE;
  321.     }
  322.  
  323.     return TRUE;
  324. }
  325.  
  326. int cEditable::walk_sub_editables(int (*callback)(cEditable *e))
  327. {
  328.     cEditable *e, *n;
  329.  
  330.     for (e = sub_editables; e != 0; e = n)
  331.     {
  332.         n = (cEditable *)e->next;
  333.  
  334.         if (e->sub_editables != 0 && !e->sub_editables->walk_sub_editables(callback))
  335.             return FALSE;
  336.  
  337.         if (!callback(e))
  338.             return FALSE;
  339.     }
  340.  
  341.     return TRUE;
  342. }
  343.  
  344. void cEditable::write()
  345. {
  346.     if (selected)
  347.         rectfill(surface, x - 2, y - 2, x + 2, y + 2, green);
  348.     else
  349.         rect(surface, x - 2, y - 2, x + 2, y + 2, green);
  350. }
  351.  
  352. int cEditable::check_drag(int dx, int dy)
  353. {
  354.     return TRUE;
  355. }
  356.  
  357. void cEditable::drag(int dx, int dy)
  358. {
  359. }
  360.  
  361. void cEditable::remove()
  362. {
  363.     cGameObject *t = obj;
  364.     
  365.     delete this;
  366.     delete t;
  367. }
  368.  
  369. void cEditable::create_context_menu(CMenu *menu)
  370. {
  371. }
  372.  
  373. void cEditable::execute_context_menu(int id)
  374. {
  375. }
  376.  
  377. cEditableGameObject::cEditableGameObject(cGameObject *obj, int select)
  378.         : cEditable(&editables, obj, select)
  379. {
  380.     set_position(obj->x, obj->y);
  381. }
  382.  
  383. int cEditableGameObject::check_drag(int dx, int dy)
  384. {
  385.     int xe = obj->x + dx, ye = obj->y + dy;
  386.  
  387.     obj->set_position(xe, ye);
  388.  
  389.     int rv = obj->x == xe && obj->y == ye;
  390.  
  391.     obj->set_position(x, y);
  392.  
  393.     return rv;
  394. }
  395.  
  396. void cEditableGameObject::drag(int dx, int dy)
  397. {
  398.     // Move object
  399.  
  400.     obj->make_dirty();
  401.     obj->set_position(obj->x + dx, obj->y + dy);
  402.     obj->update_list();
  403.     obj->make_dirty();
  404.  
  405.     // Set marker position
  406.  
  407.     set_position(obj->x, obj->y);
  408. }
  409.  
  410. cEditableWaypoint::cEditableWaypoint(cGameObject *obj, cSpot *_waypoint, int select)
  411.         : cEditable(&obj->editable->sub_editables, obj, select)
  412. {
  413.     waypoint = _waypoint;
  414.  
  415.     set_position(waypoint->x, waypoint->y);    
  416. }
  417.  
  418. void cEditableWaypoint::write()
  419. {
  420.     if (waypoint->prev == 0)
  421.         dashedline(surface, x, y, obj->x, obj->y, gray);
  422.     else
  423.         dashedline(surface, x, y, ((cSpot *)waypoint->prev)->x, ((cSpot *)waypoint->prev)->y, white);
  424.  
  425.     cEditable::write();
  426. }
  427.  
  428. int cEditableWaypoint::check_drag(int dx, int dy)
  429. {
  430.     return x + dx >= surface->edge && x + dx < surface->w - surface->edge;
  431. }
  432.  
  433. void cEditableWaypoint::drag(int dx, int dy)
  434. {
  435.     waypoint->set_position(waypoint->x + dx, waypoint->y + dy);
  436.  
  437.     set_position(waypoint->x, waypoint->y);
  438. }
  439.  
  440. void cEditableWaypoint::remove()
  441. {
  442.     cSpot *t = waypoint;
  443.  
  444.     delete this;
  445.     delete t;
  446. }
  447.  
  448. void cEditableWaypoint::create_context_menu(CMenu *menu)
  449. {
  450.     menu->AppendMenu(MF_ENABLED, ID_CONTEXT_0, _T("Insert Point &After"));
  451.     menu->AppendMenu(MF_ENABLED, ID_CONTEXT_1, _T("Insert Point &Before"));
  452.     menu->AppendMenu(MF_ENABLED, ID_CONTEXT_2, _T("&Delete"));
  453. }
  454.  
  455. void cEditableWaypoint::execute_context_menu(int id)
  456. {
  457.     cSpot *s;
  458.  
  459.     switch(id)
  460.     {
  461.     case 0:
  462.         // Insert waypoint after this one
  463.  
  464.         s = new cSpot(&obj->waypoints, waypoint->next == 0? x + 10 : (((cSpot *)waypoint->next)->x + x) / 2, waypoint->next == 0? y + 10 : (((cSpot *)waypoint->next)->y + y) / 2);
  465.         s->move_after(waypoint);
  466.  
  467.         // Create editable for it
  468.  
  469.         new cEditableMovingStructureWaypoint(obj, s, FALSE);
  470.  
  471.         break;
  472.  
  473.     case 1:
  474.         // Insert waypoint before this one
  475.  
  476.         s = new cSpot(&obj->waypoints, ((waypoint->prev == 0? obj->x : ((cSpot *)waypoint->prev)->x) + x) / 2, ((waypoint->prev == 0? obj->y : ((cSpot *)waypoint->prev)->y) + y) / 2);
  477.         s->move_before(waypoint);
  478.         
  479.         // Create editable for it
  480.  
  481.         new cEditableMovingStructureWaypoint(obj, s, FALSE);
  482.  
  483.         break;
  484.  
  485.     case 2:
  486.         // Delete this editable
  487.  
  488.         remove();
  489.  
  490.         break;
  491.     }
  492. }
  493.  
  494. void cEditableMovingStructure::create_context_menu(CMenu *menu)
  495. {
  496.     menu->AppendMenu(MF_ENABLED, ID_CONTEXT_0, _T("&Add Point"));
  497.     menu->AppendMenu(MF_SEPARATOR, 0, _T(""));
  498.     menu->AppendMenu(MF_ENABLED, ID_CONTEXT_1, _T("&Properties..."));
  499. }
  500.  
  501. void cEditableMovingStructure::execute_context_menu(int id)
  502. {
  503.     cSpot *s;
  504.  
  505.     switch(id)
  506.     {
  507.     case 0:
  508.         // Create waypoint
  509.  
  510.         s = new cSpot(&obj->waypoints, obj->waypoints == 0? obj->x + 10 : (obj->waypoints->x + obj->x) / 2, obj->waypoints == 0? obj->y + 10 : (obj->waypoints->y + obj->y) / 2);
  511.         s->move_before(obj->waypoints);
  512.  
  513.         // Create editable for it
  514.  
  515.         new cEditableMovingStructureWaypoint(obj, s, FALSE);
  516.  
  517.         break;
  518.  
  519.     case 1:
  520.         CMstructDlg d((cMovingStructure *)obj);
  521.         d.DoModal();
  522.         break;
  523.     }
  524. }
  525.  
  526. void cEditableMovingStructureWaypoint::create_context_menu(CMenu *menu)
  527. {
  528.     cEditableWaypoint::create_context_menu(menu);
  529.  
  530.     menu->AppendMenu(MF_SEPARATOR, 0, _T(""));
  531.     menu->AppendMenu(MF_ENABLED, ID_CONTEXT_3, _T("&Properties..."));
  532. }
  533.  
  534. void cEditableMovingStructureWaypoint::execute_context_menu(int id)
  535. {
  536.     if (id == 3)
  537.     {
  538.         CMstructDlg d((cMovingStructure *)obj);
  539.         d.DoModal();
  540.     }
  541.     else
  542.     {
  543.         cEditableWaypoint::execute_context_menu(id);
  544.     }
  545. }
  546.  
  547. void cEditableTurret::write()
  548. {
  549.     // Write dashed lines for rotation start and end
  550.  
  551.     dashedline(surface, x, y, x + (int)(cos(((cTurret *)obj)->rotation_start) * TURRET_DASH_LINE), y + (int)(sin(((cTurret *)obj)->rotation_start) * TURRET_DASH_LINE), green);
  552.     dashedline(surface, x, y, x + (int)(cos(((cTurret *)obj)->rotation_end) * TURRET_DASH_LINE), y + (int)(sin(((cTurret *)obj)->rotation_end) * TURRET_DASH_LINE), red);
  553.  
  554.     // Call base class
  555.  
  556.     cEditableGameObject::write();
  557. }
  558.  
  559. void cEditableTurret::create_context_menu(CMenu *menu)
  560. {
  561.     menu->AppendMenu(MF_ENABLED, ID_CONTEXT_0, _T("&Properties..."));
  562. }
  563.  
  564. void cEditableTurret::execute_context_menu(int)
  565. {
  566.     CTurretDlg d((cTurret *)obj);
  567.     d.DoModal();
  568. }